module ysyx_22040213_div(
	input clk,
	input rst,
	input div_valid,
	input flush,
//	input divw,
	input [1:0] div_signed,
	input [63:0] dividend,
	input [63:0] divisor,
	output div_ready,
	output reg out_valid,
	output reg [63:0] quotient,
	output reg [63:0] remainder

);
`define YSYX_040213_XLEN 64
`define YSYX_040213_XXLEN 128

/* verilator lint_off UNUSED */

`define DIV_IDLE    2'b00
`define DIV_DIVING  2'b01
`define DIV_END     2'b10

reg [127:0] div_dend;
reg [63:0]  div_sor;
reg [63:0]  div_quo;
wire [64:0]  div_rem;
reg [64:0] rem;
reg [5:0] div_times;
reg [1:0] div_state;
wire quo_neg;
wire rem_neg;
wire [63:0] dividend_abs;
wire [63:0] divisor_abs;

assign div_ready = div_state == `DIV_IDLE;
assign div_rem = (div_dend[127:63] - {{1'b0},{div_sor}}); 
assign quo_neg = &div_signed & ~(dividend[63] & divisor[63]) & (dividend[63] || divisor[63]);
//assign quo_neg = &div_signed & (dividend[63] & divisor[63]);
assign rem_neg = &div_signed & dividend[63];
assign dividend_abs = ~dividend + `YSYX_040213_XLEN'b1;
assign divisor_abs  = ~divisor  + `YSYX_040213_XLEN'b1;


wire [64:0] dend = div_dend[127:63];
wire [64:0] sor  = {{1'b0},{div_sor}};

always @(posedge clk)begin
  if(rst || flush)begin
    div_dend <= 128'b0;
    div_sor <= 64'b0;
    div_quo <= 64'b0;
    div_times <= 6'b111111;
    div_state <= `DIV_IDLE;
    rem <= 65'b0;
  end else begin
    case(div_state)
      `DIV_IDLE: begin
        if(div_valid)begin
	  div_state <= `DIV_DIVING;
	  out_valid <= 1'b0;
//	  div_dend <= {{64'b0},{dividend}};
//	  div_sor <= divisor;
          div_dend <= &div_signed & dividend[`YSYX_040213_XLEN - 1] ? {`YSYX_040213_XLEN'b0, dividend_abs} : {`YSYX_040213_XLEN'b0, dividend};
          div_sor  <= &div_signed & divisor[`YSYX_040213_XLEN - 1]  ? divisor_abs : divisor;

	  div_times <= 6'b111111;
	end else begin
	  div_state <= `DIV_IDLE;
	  out_valid <= 1'b0;
	end
      end
      `DIV_DIVING: begin
	if(div_times != 0)begin
	  div_times <= div_times - 1;
	  div_quo[div_times] <= div_rem[64] ? 1'b0 : 1'b1;
	  div_dend <=  div_rem[64] ? {div_dend[126:0],{1'b0}} : {{div_rem[63:0]},{div_dend[62:0]},{1'b0}}; 
        end else begin
	  div_quo[div_times] <= div_rem[64] ? 1'b0 : 1'b1;
	  rem <= div_rem[64] ? div_rem + {{1'b0},{div_sor}} : div_rem;
	  div_state <= `DIV_END;
	end
      end
      `DIV_END: begin
	remainder <= (rem[64] & ~rem_neg) || (~rem[64] & rem_neg) ? ~rem[63:0] + 1 : rem[63:0];
	quotient  <= (div_quo[63] & ~quo_neg) || (~div_quo[63] & quo_neg) ? ~div_quo[63:0] + 1 : div_quo;
	out_valid <= 1'b1;
	div_state <= `DIV_IDLE;
      end
      default: div_state <= `DIV_IDLE;
    endcase
  end
end
endmodule
